package com.shenhonghui.twins.slice;

import com.shenhonghui.twins.CrossDevicePlayerInterfaceProxy;
import com.shenhonghui.twins.ResourceTable;
import com.shenhonghui.twins.utils.DeviceUtils;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.ability.IAbilityConnection;
import ohos.aafwk.ability.IAbilityContinuation;
import ohos.aafwk.content.Intent;
import ohos.aafwk.content.IntentParams;
import ohos.aafwk.content.Operation;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.Button;
import ohos.agp.components.Component;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.utils.Color;
import ohos.bundle.ElementName;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;
import ohos.multimodalinput.event.TouchEvent;
import ohos.rpc.IRemoteObject;
import ohos.rpc.RemoteException;

import java.util.HashMap;
import java.util.Iterator;

public class PianoAbilitySlice extends AbilitySlice implements IAbilityContinuation {
    private Button choosePhone;
    private Button connection;
    private static Button soundType;
    private Button demo;

    private static Button buttons[];

    private int buttonId[];

    private static ShapeElement shapeElement;
    private static ShapeElement shapeButtonWhite;
    private static ShapeElement shapeButtonBlack;
    private static ShapeElement shapeElementGray;

    private Operation localOperation;
    private Operation remoteOperation;
    private Operation remoteMainOperation;

    private Intent localIntent;
    private Intent remoteIntent;
    private Intent remoteMainIntent;

    private boolean emptyDevice;

    private String data = null;

    private int width = 158;

    private enum PlayMode {
        None,
        MASTER,
        SLAVE,
        MASTER_SLAVE,
    }

    private static PlayMode playMode = PlayMode.None;

    private DirectionalLayout upKeysLayout;
    private DirectionalLayout downKeysLayout;
    private DirectionalLayout blackUpLayout;
    private DirectionalLayout blackDownLayout;

    private boolean isConnected = false;


    public static final int PLAY_MUSIC_MSG = 100;
    public static final int SOUND_TYPE = 101;


    //连接本地服务
    CrossDevicePlayerInterfaceProxy localPlayerMusicInterfaceProxy = null;
    private IAbilityConnection localAbilityConnection = new IAbilityConnection() {
        @Override
        public void onAbilityConnectDone(ElementName elementName, IRemoteObject iRemoteObject, int i) {
            localPlayerMusicInterfaceProxy = new CrossDevicePlayerInterfaceProxy(iRemoteObject);
        }

        @Override
        public void onAbilityDisconnectDone(ElementName elementName, int i) {
            localPlayerMusicInterfaceProxy = null;
        }
    };

    //连接远程服务
    CrossDevicePlayerInterfaceProxy remotePlayerMusicInterfaceProxy = null;
    private IAbilityConnection remoteAbilityConnection = new IAbilityConnection() {
        @Override
        public void onAbilityConnectDone(ElementName elementName, IRemoteObject iRemoteObject, int i) {
            remotePlayerMusicInterfaceProxy = new CrossDevicePlayerInterfaceProxy(iRemoteObject);
        }

        @Override
        public void onAbilityDisconnectDone(ElementName elementName, int i) {
            remotePlayerMusicInterfaceProxy = null;
        }
    };

    //开始迁移 AbilitySlice可以不实现默认返回true Ability 必须实现
    @Override
    public boolean onStartContinuation() {
        return true;
    }

    //保存数据
    @Override
    public boolean onSaveData(IntentParams intentParams) {
        intentParams.setParam("data","remote");
        return true;
    }

    //解压数据
    @Override
    public boolean onRestoreData(IntentParams intentParams) {
        data = intentParams.getParam("data").toString();
        return true;
    }

    //迁移完成
    @Override
    public void onCompleteContinuation(int i) {
        //WidgetHelper.showTips(PianoAbilitySlice.this,"迁移成功" + i);
        if(connectRemoteServices()) {
            soundType.setText("同时播放");
            connection.setText("已经连接");
            playMode = PlayMode.MASTER_SLAVE;
            connection.setClickable(false);
            connection.setTextColor(Color.GRAY);
            choosePhone.setClickable(false);
            choosePhone.setTextColor(Color.GRAY);
            isConnected = true;
            soundType.setClickable(true);
            soundType.setTextColor(Color.BLACK);
        }
    }

    @Override
    public void onRemoteTerminated() {
        isConnected = false;
    }

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);
        Init();
        upKeysLayout = (DirectionalLayout) findComponentById(ResourceTable.Id_UpKeys);
        downKeysLayout = (DirectionalLayout) findComponentById(ResourceTable.Id_DownKeys);
        blackUpLayout = (DirectionalLayout) findComponentById(ResourceTable.Id_backUp);
        blackDownLayout = (DirectionalLayout) findComponentById(ResourceTable.Id_backDown);
        if (data == null) {
            downKeysLayout.setLayoutConfig(new DirectionalLayout.LayoutConfig(0, 0));
            blackDownLayout.setLayoutConfig(new DirectionalLayout.LayoutConfig(0, 0));
        } else {
            upKeysLayout.setLayoutConfig(new DirectionalLayout.LayoutConfig(0, 0));
            blackUpLayout.setLayoutConfig(new DirectionalLayout.LayoutConfig(0, 0));
            choosePhone.setClickable(false);
            choosePhone.setTextColor(Color.GRAY);
            soundType.setClickable(false);
            soundType.setTextColor(Color.GRAY);
            connection.setClickable(false);
            connection.setTextColor(Color.GRAY);
            if (connectRemoteServices()) {
                connection.setText("已经连接");
                choosePhone.setText(DeviceUtils.getRemoteDevice().get(0).getDeviceName());
                soundType.setText("同时播放");
                playMode = PlayMode.MASTER_SLAVE;
                isConnected = true;
            }
        }
        upKeysLayout.setTouchEventListener(touchEventListener);
        downKeysLayout.setTouchEventListener(touchEventListener);
    }

    @Override
    protected void onActive() {
        super.onActive();
    }

    @Override
    protected void onStop() {
        super.onStop();
        disconnectAbility(localAbilityConnection);
        stopAbility(localIntent);
        if(isConnected) {
            disconnectAbility(remoteAbilityConnection);
            stopAbility(remoteIntent);
            stopAbility(remoteMainIntent);
        }
    }

    private boolean connectRemoteServices() {
        if(!DeviceUtils.getRemoteDevice().isEmpty()) {
            try {
                return connectAbility(remoteIntent, remoteAbilityConnection);
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
        return false;
    }

    private Component.TouchEventListener touchEventListener = new Component.TouchEventListener() {
        @Override
        public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
            int pointerIndex = touchEvent.getIndex();
            int pointerId = touchEvent.getPointerId(pointerIndex);
            float x = touchEvent.getPointerPosition(pointerIndex).getX();
            float y = touchEvent.getPointerPosition(pointerIndex).getY();
            switch (touchEvent.getAction()) {
                case TouchEvent.PRIMARY_POINT_DOWN:
                case TouchEvent.OTHER_POINT_DOWN:
                    onFingerDown(pointerId, x, y);
                    break;
                case TouchEvent.OTHER_POINT_UP:
                case TouchEvent.PRIMARY_POINT_UP:
                    onFingerUp(pointerId, x, y);
                    break;
                case TouchEvent.POINT_MOVE:
                    int pointCount = touchEvent.getPointerCount();
                    for (int i = 0 ; i < pointCount; i++) {
                        onFingerMove(touchEvent.getPointerId(i),touchEvent.getPointerPosition(i).getX(),touchEvent.getPointerPosition(i).getY());
                    }
                    break;
                case TouchEvent.CANCEL:
                    onAllFingersUp();
                    break;
            }
            return false;
        }
    };

    private void Init() {
        emptyDevice = DeviceUtils.getRemoteDevice().isEmpty();
        choosePhone = (Button) findComponentById(ResourceTable.Id_phone);
        connection = (Button) findComponentById(ResourceTable.Id_connect);
        soundType = (Button) findComponentById(ResourceTable.Id_soundType);
        demo = (Button) findComponentById(ResourceTable.Id_demo);
        choosePhone.setClickedListener(clickedListener);
        connection.setClickedListener(clickedListener);
        soundType.setClickedListener(clickedListener);
        demo.setClickedListener(clickedListener);

        localOperation = new Intent.OperationBuilder()
                .withDeviceId("")
                .withBundleName("com.shenhonghui.twins")
                .withAbilityName("com.shenhonghui.twins.PlayAbility")
                .withFlags(Intent.FLAG_START_FOREGROUND_ABILITY)
                .build();
        localIntent = new Intent();
        localIntent.setOperation(localOperation);
        startAbility(localIntent);
        try {
            connectAbility(localIntent, localAbilityConnection);
        }catch (Exception e) {
            e.printStackTrace();
        }

        if(!emptyDevice) {
            choosePhone.setText(DeviceUtils.getRemoteDevice().get(0).getDeviceName());
            remoteOperation = new Intent.OperationBuilder()
                    .withDeviceId(DeviceUtils.getRemoteDevice().get(0).getDeviceId())
                    .withBundleName("com.shenhonghui.twins")
                    .withAbilityName("com.shenhonghui.twins.PlayAbility")
                    .withFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE)
                    .build();

            remoteMainOperation = new Intent.OperationBuilder()
                    .withDeviceId(DeviceUtils.getRemoteDevice().get(0).getDeviceId())
                    .withBundleName("com.shenhonghui.twins")
                    .withAbilityName("com.shenhonghui.twins.MainAbility")
                    .withFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE)
                    .build();

            remoteIntent = new Intent();
            remoteIntent.setOperation(remoteOperation);

            remoteMainIntent = new Intent();
            remoteMainIntent.setOperation(remoteMainOperation);
        } else {
            choosePhone.setText("没有在线的手机");
        }

        buttonId = new int[48];
        buttonId[0] = ResourceTable.Id_PianoC;
        buttonId[1] = ResourceTable.Id_PianoD;
        buttonId[2] = ResourceTable.Id_PianoE;
        buttonId[3] = ResourceTable.Id_PianoF;
        buttonId[4] = ResourceTable.Id_PianoG;
        buttonId[5] = ResourceTable.Id_PianoA;
        buttonId[6] = ResourceTable.Id_PianoB;

        buttonId[7] = ResourceTable.Id_Pianoc;
        buttonId[8] = ResourceTable.Id_Pianod;
        buttonId[9] = ResourceTable.Id_Pianoe;
        buttonId[10] = ResourceTable.Id_Pianof;
        buttonId[11] = ResourceTable.Id_Pianog;
        buttonId[12] = ResourceTable.Id_Pianoa;
        buttonId[13] = ResourceTable.Id_Pianob;

        buttonId[14] = ResourceTable.Id_Pianoc1;
        buttonId[15] = ResourceTable.Id_Pianod1;
        buttonId[16] = ResourceTable.Id_Pianoe1;
        buttonId[17] = ResourceTable.Id_Pianof1;
        buttonId[18] = ResourceTable.Id_Pianog1;
        buttonId[19] = ResourceTable.Id_Pianoa1;
        buttonId[20] = ResourceTable.Id_Pianob1;

        buttonId[21] = ResourceTable.Id_Pianoc2;
        buttonId[22] = ResourceTable.Id_Pianod2;
        buttonId[23] = ResourceTable.Id_Pianoe2;
        buttonId[24] = ResourceTable.Id_Pianof2;
        buttonId[25] = ResourceTable.Id_Pianog2;
        buttonId[26] = ResourceTable.Id_Pianoa2;
        buttonId[27] = ResourceTable.Id_Pianob2;

        buttonId[28] = ResourceTable.Id_PianoCm;
        buttonId[29] = ResourceTable.Id_PianoDm;
        buttonId[30] = ResourceTable.Id_PianoFm;
        buttonId[31] = ResourceTable.Id_PianoGm;
        buttonId[32] = ResourceTable.Id_PianoAm;

        buttonId[33] = ResourceTable.Id_Pianocm;
        buttonId[34] = ResourceTable.Id_Pianodm;
        buttonId[35] = ResourceTable.Id_Pianofm;
        buttonId[36] = ResourceTable.Id_Pianogm;
        buttonId[37] = ResourceTable.Id_Pianoam;

        buttonId[38] = ResourceTable.Id_Pianoc1m;
        buttonId[39] = ResourceTable.Id_Pianod1m;
        buttonId[40] = ResourceTable.Id_Pianof1m;
        buttonId[41] = ResourceTable.Id_Pianog1m;
        buttonId[42] = ResourceTable.Id_Pianoa1m;

        buttonId[43] = ResourceTable.Id_Pianoc2m;
        buttonId[44] = ResourceTable.Id_Pianod2m;
        buttonId[45] = ResourceTable.Id_Pianof2m;
        buttonId[46] = ResourceTable.Id_Pianog2m;
        buttonId[47] = ResourceTable.Id_Pianoa2m;

        buttons = new Button[48];
        for (int i = 0; i < buttons.length; i++) {
            buttons[i] = (Button)findComponentById(buttonId[i]);
        }

        shapeElement = new ShapeElement();
        shapeButtonWhite = new ShapeElement();
        shapeButtonBlack = new ShapeElement();
        shapeElementGray = new ShapeElement();
        shapeButtonWhite.setRgbColor(new RgbColor(0xff,0xff,0xff));
        shapeButtonWhite.setStroke(3,new RgbColor(0x60,0x5C,59));
        shapeButtonWhite.setCornerRadius(30.0f);
        shapeButtonBlack.setRgbColor(new RgbColor(0x00,0x00,0x00));
        shapeButtonBlack.setStroke(3,new RgbColor(0x60,0x5C,0x59));
        shapeButtonBlack.setCornerRadius(30.0f);
        shapeElement.setRgbColor(new RgbColor(0xFC,0x60,0x2F));
        shapeElement.setStroke(3,new RgbColor(0x0A,0x00,0x00));
        shapeElement.setCornerRadius(30.0f);
        shapeElementGray.setRgbColor(new RgbColor(0x60,0x5C,0x59));
        shapeElementGray.setStroke(3, new RgbColor(0x60,0x5C,0x59));
        shapeElementGray.setCornerRadius(30.0f);
    }

    //判断某个点是否在某个按钮的范围内
    private int isInScale(float x, float y) {
        int i = 0;
        if(data == null) {
            if(y > 500) {
                i = (int) (x / width);
            }else {
                i = (int) (x / (width * 14 / 10)) + 28;
            }
        }else {
            if(y > 500) {
                i = (int) (x / width) + 14;
            }else {
                i = (int) (x / (width * 14 /10)) + 38;
            }
        }

        return i;
    }

    private Component.ClickedListener clickedListener = new Component.ClickedListener() {
        @Override
        public void onClick(Component component) {
            switch (component.getId()) {
                case ResourceTable.Id_connect:
                    if(!emptyDevice) {
                        continueAbility(DeviceUtils.getRemoteDevice().get(0).getDeviceId());
                    }
                    break;
                case ResourceTable.Id_phone:
                    if(DeviceUtils.getRemoteDevice().isEmpty()) {
                        choosePhone.setText("没有在线的手机");
                    }else {
                        choosePhone.setText(DeviceUtils.getRemoteDevice().get(0).getDeviceName());
                    }
                    break;
                case ResourceTable.Id_soundType:
                    setPlayMode();
                    break;
                case ResourceTable.Id_demo:
                    try {
                        localPlayerMusicInterfaceProxy.sendCommand(102,1);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                    break;
            }
        }
    };

    private void setPlayMode() {
        if(isConnected == false) {
            soundType.setText("本地播放");
            soundType.setClickable(false);
            soundType.setTextColor(Color.GRAY);
            return;
        }
        if(!emptyDevice) {
            switch (playMode) {
                case None:
                    playMode = PlayMode.MASTER;
                    soundType.setText("主机播放");
                    break;
                case MASTER:
                    playMode = PlayMode.SLAVE;
                    soundType.setText("从机播放");
                    break;
                case SLAVE:
                    playMode = PlayMode.MASTER_SLAVE;
                    soundType.setText("同时播放");
                    break;
                case MASTER_SLAVE:
                    playMode = PlayMode.None;
                    soundType.setText("各自播放");
                    break;
            }

            if(remotePlayerMusicInterfaceProxy == null) {
                if(!connectAbility(remoteIntent,remoteAbilityConnection)) {
                    //WidgetHelper.showTips(PianoAbilitySlice.this, "连接远程播放失败！");
                }
            } else {
                try {
                    remotePlayerMusicInterfaceProxy.sendCommand(SOUND_TYPE, playMode.ordinal());
                }catch (RemoteException e) {
                    e.printStackTrace();
                }
            }


        }else {
            playMode = PlayMode.MASTER;
            soundType.setText("本地播放");
            soundType.setClickable(false);
            soundType.setTextColor(Color.GRAY);
        }
    }

    private void PlayMusic(int indexPressedKey) {
        if(localPlayerMusicInterfaceProxy == null) {
            if(!connectAbility(localIntent,localAbilityConnection)) {
                //WidgetHelper.showTips(PianoAbilitySlice.this, "连接本地播放失败！");
            }
        }
        if(isConnected == true && remotePlayerMusicInterfaceProxy == null) {
            if(!connectAbility(remoteIntent,remoteAbilityConnection)) {
                //WidgetHelper.showTips(PianoAbilitySlice.this, "连接远程播放失败！");
            }
        }

        switch (playMode) {
            case None:
            case MASTER:
                try {
                    localPlayerMusicInterfaceProxy.sendCommand(PLAY_MUSIC_MSG,indexPressedKey);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                break;
            case SLAVE:
                try {
                    remotePlayerMusicInterfaceProxy.sendCommand(PLAY_MUSIC_MSG,indexPressedKey);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                break;
            case MASTER_SLAVE:
                try {
                    remotePlayerMusicInterfaceProxy.sendCommand(PLAY_MUSIC_MSG,indexPressedKey);
                    localPlayerMusicInterfaceProxy.sendCommand(PLAY_MUSIC_MSG,indexPressedKey);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                break;
        }
    }

    //处理触摸处理相关
    private HashMap<Integer, Integer> keyMap = new HashMap<>();

    private void onFingerDown(int index, float x, float y) {
        int key = isInScale(x, y);
        fireKeyDown(key);
        this.keyMap.put(index, key);
    }

    private void onFingerUp(int index, float x, float y) {
        if (this.keyMap.get(index) != null) {
            int key = this.keyMap.get(index);
            fireKeyUp(key);
            this.keyMap.remove(index);
        } else {
            int newKey = isInScale(x, y);
            fireKeyUp(newKey);
        }
    }

    private void onFingerMove(int index, float x, float y) {
        int currentKey = isInScale(x, y);
        if (this.keyMap.get(index) != null) {
            int key  = this.keyMap.get(index);
            if ((currentKey >= 0) && (currentKey != key)) {
                fireKeyDown(currentKey);
                fireKeyUp(key);
                this.keyMap.put(index, currentKey);
            }
        }
    }

    private void onAllFingersUp() {
        Iterator<Integer> localIterator = this.keyMap.values().iterator();
        while (localIterator.hasNext()) {
            fireKeyUp(localIterator.next());
        }
        this.keyMap.clear();
    }

    private void fireKeyUp(int key) {
        if (key >= 28) {
            buttons[key].setBackground(shapeButtonBlack);
        } else {
            buttons[key].setBackground(shapeButtonWhite);
        }
    }

    private void fireKeyDown(int key) {
        buttons[key].setBackground(shapeElement);
        PlayMusic(key);
    }

    private static void keyDown(int key) {
        buttons[key].setBackground(shapeElement);
    }
    private static void keyUp(int key) {
        if (key >= 28) {
            buttons[key].setBackground(shapeButtonBlack);
        } else {
            buttons[key].setBackground(shapeButtonWhite);
        }
    }

    private static EventRunner eventRunner = EventRunner.current();

    public static EventHandler getHandler(){
        return mHandler;
    }

    private static EventHandler mHandler = new EventHandler(eventRunner){
        @Override
        protected void processEvent(InnerEvent event) {
            super.processEvent(event);
            switch (event.eventId) {
                case 0:
                    playMode = PlayMode.None;
                    soundType.setText("各自播放");
                    break;
                case 1:
                    playMode = PlayMode.SLAVE;
                    soundType.setText("主机播放");
                    break;
                case 2:
                    playMode = PlayMode.MASTER;
                    soundType.setText("从机播放");
                    break;
                case 3:
                    playMode = PlayMode.MASTER_SLAVE;
                    soundType.setText("同时播放");
                    break;
            }
        }
    };
}
